#include "sshclient.h"

#include <QDir>
#include <QTcpSocket>
#include "libssh2/include/libssh2.h"
#include "libssh2/include/libssh2_sftp.h"

sshClient::sshClient(QObject *parent)
    : QObject{parent}
{}

void sshClient::copyFolder(QString strRemoteIP, QString strRemoteUser, QString strRemotePwd, QString remoteFolder, QString localFolder)
{
    connect(this, &sshClient::copySignal, this, &sshClient::copy,Qt::UniqueConnection);
    emit copySignal(strRemoteIP, strRemoteUser, strRemotePwd, remoteFolder, localFolder);
}

void sshClient::copy(QString strRemoteIP, QString strRemoteUser, QString strRemotePwd, QString remoteFolder, QString localFolder)
{
    LIBSSH2_SESSION *session = nullptr;
    LIBSSH2_SFTP *sftp_session = nullptr;

    // 初始化libssh2
    if (libssh2_init(0) != 0) {
        emit copyError("libssh2初始化失败！");
        return;
    }

    // 创建会话
    session = libssh2_session_init();
    if (!session) {
        emit copyError("创建libssh2会话失败！");
        return;
    }

    // 连接到远程主机
    QTcpSocket socket;
    socket.connectToHost(strRemoteIP, 22);
    if (!socket.waitForConnected()) {
        emit copyError("SSH无法连接到远程主机！");
        libssh2_session_free(session);
        return;
    }

    if (libssh2_session_handshake(session, socket.socketDescriptor()) != 0) {
        emit copyError("SSH握手失败！");
        libssh2_session_free(session);
        return;
    }

    // 认证
    if (libssh2_userauth_password(session, strRemoteUser.toUtf8().constData(), strRemotePwd.toUtf8().constData()) != 0) {
        emit copyError("SSH认证失败！");
        libssh2_session_disconnect(session, "正常关闭");
        libssh2_session_free(session);
        return;
    }

    // 初始化SFTP会话
    sftp_session = libssh2_sftp_init(session);
    if (!sftp_session) {
        emit copyError("初始化SFTP会话失败！");
        libssh2_session_disconnect(session, "正常关闭");
        libssh2_session_free(session);
        return;
    }


    // 开始拷贝
    if(!_copyFolder(sftp_session,remoteFolder, localFolder))
        return;

    // 清理资源
    libssh2_sftp_shutdown(sftp_session);
    libssh2_session_disconnect(session, "正常关闭");
    libssh2_session_free(session);
    libssh2_exit();
    emit copyOK();

}

bool sshClient::_copyFolder(LIBSSH2_SFTP *sftp_session,QString remoteFolder, QString localFolder)
{
    QDir().mkpath(localFolder); // 创建本地文件夹

    LIBSSH2_SFTP_HANDLE *dir = libssh2_sftp_opendir(sftp_session, remoteFolder.toUtf8().constData());
    if (!dir) {
        emit copyError(QString("无法打开远程文件夹: %1").arg(remoteFolder));
        return false;
    }

    char buffer[512];
    LIBSSH2_SFTP_ATTRIBUTES attrs;
    while (libssh2_sftp_readdir(dir, buffer, sizeof(buffer), &attrs) > 0) {
        QString fileName = QString::fromUtf8(buffer);
        if (fileName == "." || fileName == "..") continue;

        QString remoteFilePath = remoteFolder + "/" + fileName;
        QString localFilePath = localFolder + "/" + fileName;

        if (LIBSSH2_SFTP_S_ISDIR(attrs.permissions)) {
            // 如果是文件夹，递归拷贝
            if(!_copyFolder(sftp_session,remoteFilePath, localFilePath))
                return false;
        } else {
            // 如果是文件，下载到本地
            LIBSSH2_SFTP_HANDLE *file = libssh2_sftp_open(sftp_session, remoteFilePath.toUtf8().constData(), LIBSSH2_FXF_READ, 0);
            if (!file) {
                emit copyError(QString("无法打开远程文件: %1").arg(remoteFilePath));
                return false;
            }

            QFile localFile(localFilePath);
            if (!localFile.open(QIODevice::WriteOnly)) {
                emit copyError(QString("无法创建本地文件: %1").arg(localFilePath));
                libssh2_sftp_close(file);
                return false;
            }

            char fileBuffer[4096];
            ssize_t bytesRead;
            while ((bytesRead = libssh2_sftp_read(file, fileBuffer, sizeof(fileBuffer))) > 0) {
                localFile.write(fileBuffer, bytesRead);
            }

            localFile.close();
            libssh2_sftp_close(file);
        }
    }

    libssh2_sftp_closedir(dir);
    return true;
}
